﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.VCCodeModel;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TextManager.Interop;
using System.Runtime.InteropServices;
using EnvDTE;

namespace GordonKristan.codeclean
{
	class CodeCleanInterface
	{
		/// <summary>
		/// Called when user wants to style a file.
		/// </summary>
		public void styleFile()
		{
			//Perform the style on the current window text
			RemoveModule module = new RemoveModule(getFileText());
			module.styleFile();
			setFileText(module.getText());
		}

		/// <summary>
		/// Called when user opens comment manager.
		/// </summary>
		public void commentManager()
		{
			//Open comment manager form with this file.
			CommentManager man = new CommentManager(getFileText());
			man.ShowDialog();
			if (man.success)
			{
				setFileText(man.getText());
			}
		}

		/// <summary>
		/// Called when the user chooses to alphabetize lines.
		/// </summary>
		public void alphabetizeLines()
		{
			//First, get the selected lines
			IVsTextManager textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
			IVsTextView textView;
			//if there's an active document, fetch and return the text
			if (textManager.GetActiveView(1, null, out textView) != 0)
			{
				return;
			}
			int startline, endline, startcol, endcol;
			textView.GetSelection(out startline, out startcol, out endline, out endcol);
			//Now let's get the text lines
			String document = getFileText();
			//Have them sorted
			AlphabetizingModule mod = new AlphabetizingModule(document, startline, endline);
			//Replace them
			setFileText(mod.getText());
		}

		/// <summary>
		/// Get the current document in the form of a String
		/// </summary>
		/// <returns>String containing document text</returns>
		private String getFileText()
		{
			//Get the text manager
			IVsTextManager textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
			IVsTextView textView;
			//if there's an active document, fetch and return the text
			if (textManager.GetActiveView(1, null, out textView) == 0)
			{
				//Get the lines in the document
				IVsTextLines lines;
				textView.GetBuffer(out lines);
				//Get the position of the very last character
				int numlines, column;
				lines.GetLineCount(out numlines);
				lines.GetLengthOfLine(numlines - 1, out column);
				//Get the actual text, since we want a full string, not lines
				String document;
				textView.GetTextStream(0, 0, numlines - 1, column, out document);
				//Normalize line endings
				document.Replace("\n", "\r\n");
				document.Replace("\r\r\n", "\r\n");
				return document;
			}
			return "";
		}

		/// <summary>
		/// Set the active documentString to the new text
		/// </summary>
		/// <param name="newText">New text of the documentString</param>
		private void setFileText(String newText)
		{
			//Get the text manager service and grab the current documentString.
			IVsTextManager textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
			IVsTextView textView;
			//Check to see if there's an active documentString
			//S_OK isn't active, so we'll use it's value of 0
			if (textManager.GetActiveView(1, null, out textView) == 0)
			{
				//Get the lines in the documentString
				IVsTextLines lines;
				textView.GetBuffer(out lines);
				//Get the position of the very last character
				int numlines, column;
				lines.GetLineCount(out numlines);
				lines.GetLengthOfLine(numlines - 1, out column);
				//Now replace all lines with our new string
				IntPtr ptr = Marshal.StringToCoTaskMemAuto(newText);
				lines.ReplaceLines(0, 0, numlines - 1, column, ptr, newText.Length, null);
			}
		}

		/// <summary>
		/// Get the current documentString in the form of a lines object
		/// </summary>
		/// <returns>Lines object containing documentString</returns>
		private IVsTextLines getFileLines()
		{
			//Get the text manager
			IVsTextManager textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
			IVsTextView textView;
			//if there's an active documentString, fetch and return the lines
			if (textManager.GetActiveView(1, null, out textView) == 0)
			{
				IVsTextLines lines;
				textView.GetBuffer(out lines);
				return lines;
			}
			return null;
		}

		/// <summary>
		/// Set the active documentString to the new set of lines
		/// </summary>
		/// <param name="newLines">New lines of the documentString</param>
		private void setFileLines(IVsTextLines newLines)
		{
			//Get the text manager
			IVsTextManager textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
			IVsTextView textView;
			//if there's an active documentString, fetch and return the lines
			if (textManager.GetActiveView(1, null, out textView) == 0)
			{
				textView.SetBuffer(newLines);
			}
		}
	}
}
